<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <script type="text/javascript" src="../jsunit/app/jsUnitCore.js"></script>
    <script type="text/javascript" src="../../src/objx.test.js"></script>
    <script type="text/javascript" src="../../src/objx.js"></script>

                <script type="text/javascript">

		var counter = 0;

		function getTestClass()
		{
			return Class({ 
				getFirstName: function() { return this.first; },
				getLastName:  function() { return this.last; }
			});
		}
		
		function getInstance()
		{
			var c = getTestClass();
			return new c();
		}

		function test_eventClassMethods()
		{
			
			var inst = getInstance();
			
			assertNotUndefined("inst.notify", inst.notify);
			assertNotUndefined("inst.observe", inst.observe)
			
		}
		
    	function test_observe()
		{
			
			var inst = getInstance();
			
			// reset the counter
			counter = 0;
			
			var callback = function(){ return counter++; }
			
			// observe an event
			inst.observe("bang", callback)
		
			// ensure internal eventing stuff was added
			assertNotUndefined("inst.objx", inst.objx);
			assertNotUndefined("inst.objx.ev", inst.objx.ev);
			assertNotUndefined("inst.objx.ev['bang'] expected to be an array.", inst.objx.ev['bang']);
			
			// make sure the correct callback was added
			assertEquals("inst.objx.ev.bang[0] expected to be callback.", callback, inst.objx.ev.bang[0])
			
		}
		
		function test_returnOfObserveIsInstance()
		{
			
			var inst = getInstance();
			
			var result = inst.observe("bang", function(){});
			
			assertEquals("Result from 'observe' expected to be the instance.", inst, result);
			
		}
		
		function test_returnOfNotifyIsInstance()
		{
			
			var inst = getInstance();
			
			var result = inst.notify("some_event");
			
			assertEquals("Result from 'notify' expected to be the instance.", inst, result);
			
		}
		
		function test_notify_noData()
		{
			
			var inst = getInstance();
			
			// reset the counter
			counter = 0;
			
			var callback = function(){ counter++; }
			
			// observe an event
			inst.observe("bang", callback)
		
			inst.notify("bang");
			
			assertEquals("Callback method doesn't seem to have been called.", 1, counter);
		
		}
		
		function test_senderSentInContextToCallback()
		{
			
			var inst = getInstance();
			
			counter = 0;
			
			inst.observe("bang", function(sender){
				counter++;
				assertEquals("Context object expected to hold the sender - which should equal the instance sending the event.", 
					inst, sender);
			}).notify("bang");

			assertEquals("Callback not called.", 1, counter);
			
		}
		
		function test_argumentsSentToCallback()
		{
			
			// any arguments passed in after the event name 
			// i.e.    .notify(eventName, arg1, arg2, arg3)
			// should also be passed along to the callback too
			
			// we will pass three arguments
			// "first"
			// 2
			// "last"
			
			var inst = getInstance();
			
			counter = 0;
			
			inst.observe("bang", function(context){
				
				// make sure we got a total of 4 arguments
				// (one context plus the three arguments we pass in later)
				assertEquals(4, arguments.length);
				
				// also make sure the argument match the expected ones
				assertEquals("1st arg sent to notify was not 2nd arg in callback", "first", arguments[1]);
				assertEquals("2nd arg sent to notify was not 3rd arg in callback", 2, arguments[2]);
				assertEquals("3rd arg sent to notify was not 4th arg in callback", "last", arguments[3]);
				
				// increase the counter
				counter++;
				
			});
			
			// notify it with the arguments
			inst.notify("bang", "first", 2, "last");
			
			assertEquals("Callback not called.", 1, counter);
			
		}

        function test_eventsOnNormalObject()
        {
        
            var normalObj = {};
            
            counter = 0;
            
            assertUndefined(normalObj.objx);
            
            objx.observe(normalObj, "bang", function(){
                counter++;
            });
            
            assertNotUndefined(normalObj.objx);
            
            // raise the event
            objx.notify(normalObj, "bang");
            
            assertEquals("Callback was not called.", 1, counter);
        
        }


		function test_multipleEvents_withoutUsingBind_noContextRequired_usingDirectMethods(){
        
        	var counter = 0;
        
        	var MyClass = Class({
        		onOne: Event(),
        		onTwo: Event(),
        		onThree: Event(),
        		onFour: Event(),
        		onFive: Event()
        	});
        	
        	var instance = new MyClass();
        	
        	var callbacks = {

        		onOne: function(context, more){
        			counter += 2;
        		},
        		onTwo: function(context, more){

        			counter += 3;
        			counter += more;
        			
        		},
        		onThree: function(){
        			counter += 4;
        		},
        		onFour: function(){
        			counter += 5;
        		},
        		onFive: function(){
        			counter += 6;
        		}
        	}

        	objx.observe(instance, "onOne", callbacks.onOne);
        	objx.observe(instance, "onTwo", callbacks.onTwo);
        	objx.observe(instance, "onThree", callbacks.onThree);
        	objx.observe(instance, "onFour", callbacks.onFour);
        	objx.observe(instance, "onFive", callbacks.onFive);
        	
        	assertEquals(0, counter);
        	
        	//instance.onOne();
        	objx.notify(instance, "onOne");
        	
        	assertEquals(2, counter);
        	objx.notify(instance, "onTwo", 10);
           	assertEquals(15, counter);
        	objx.notify(instance, "onThree");
			assertEquals(19, counter);
        	objx.notify(instance, "onFour");
        	assertEquals(24, counter);
        	objx.notify(instance, "onFive");
        	assertEquals(30, counter);
        
        }
        


        function test_multipleEvents_usingBind_usingDirectMethods(){
        
        	var MyClass = Class({
        		onOne: Event(),
        		onTwo: Event(),
        		onThree: Event(),
        		onFour: Event(),
        		onFive: Event()
        	});
        	
        	var instance = new MyClass();
        	
        	var callbacks = {
        		increaseAmount: 2,
        		grandTotal: 0,
        		onOne: function(){
        			this.grandTotal += this.increaseAmount;
        		},
        		onTwo: function(context, more){

        			this.grandTotal += this.increaseAmount + 1;
        			this.grandTotal += more;
        		},
        		onThree: function(){
        			this.grandTotal += this.increaseAmount + 2;
        		},
        		onFour: function(){
        			this.grandTotal += this.increaseAmount + 3;
        		},
        		onFive: function(){
        			this.grandTotal += 6;
        		}        		
        	}

			objx.bind(callbacks.onOne, callbacks)

        	objx.observe(instance, "onOne", objx.bind(callbacks.onOne, callbacks));
        	objx.observe(instance, "onTwo", objx.bind(callbacks.onTwo, callbacks));
        	objx.observe(instance, "onThree", objx.bind(callbacks.onThree, callbacks));
        	objx.observe(instance, "onFour", objx.bind(callbacks.onFour, callbacks));
        	objx.observe(instance, "onFive", objx.bind(callbacks.onFive, callbacks));

        	assertEquals(0, callbacks.grandTotal);

        	objx.notify(instance, "onOne");
        	
        	assertEquals(2, callbacks.grandTotal);

        	objx.notify(instance, "onTwo", 10);
        	
        	assertEquals(15, callbacks.grandTotal);

        	objx.notify(instance, "onThree");
        	
			assertEquals(19, callbacks.grandTotal);

        	objx.notify(instance, "onFour");
        	
        	assertEquals(24, callbacks.grandTotal);

        	objx.notify(instance, "onFive");
        	
        	assertEquals(30, callbacks.grandTotal);
        
        }


        
        function test_multipleEvents_usingBind_usingEventMethods(){
        
        	var MyClass = Class({
        		onOne: Event(),
        		onTwo: Event(),
        		onThree: Event(),
        		onFour: Event(),
        		onFive: Event()
        	});
        	
        	var instance = new MyClass();
        	
        	var callbacks = {
        	
        		increaseAmount: 2,
        		grandTotal: 0,
        		
        		onOne: function(){

        			this.grandTotal = this.grandTotal || 0;
        			this.grandTotal += this.increaseAmount;
        		},
        		onTwo: function(context, more){
  

  					this.grandTotal = this.grandTotal || 0;
        			this.grandTotal += this.increaseAmount + 1;
        			this.grandTotal += more;
        			
        		},
        		onThree: function(){

        			this.grandTotal = this.grandTotal || 0;
        			this.grandTotal += this.increaseAmount + 2;
        		},
        		onFour: function(){

        			this.grandTotal = this.grandTotal || 0;
        			this.grandTotal += this.increaseAmount + 3;
        		},
        		onFive: function(){

        			this.grandTotal = this.grandTotal || 0;
        			this.grandTotal += 6;
        		}        		
        	}

        	instance.onOne(objx.bind(callbacks.onOne, callbacks));
        	instance.onTwo(objx.bind(callbacks.onTwo, callbacks));
        	instance.onThree(objx.bind(callbacks.onThree, callbacks));
        	instance.onFour(objx.bind(callbacks.onFour, callbacks));
        	instance.onFive(objx.bind(callbacks.onFive, callbacks));
        	
        	assertEquals(0, callbacks.grandTotal);

        	instance.onOne();
        	
        	assertEquals("Calling onOne() notify event method did not call callback.", 2, callbacks.grandTotal);

        	instance.onTwo(10);
        	
        	assertEquals(15, callbacks.grandTotal);

        	instance.onThree();
        	
			assertEquals(19, callbacks.grandTotal);

        	instance.onFour();
        	
        	assertEquals(24, callbacks.grandTotal);
        	
        	instance.onFive();
        	
        	assertEquals(30, callbacks.grandTotal);
        
        }

		function test_shortcuts(){
		
			counter = 0;
		
    		var Dog = Class({
    			Bark: Event()
    		});
    		
    		var fido = new Dog();
    		var callback1 = function(){ counter++; }
    		var callback2 = function(){ counter++; }
    		
    		fido.Bark(callback1);
			fido.Bark(callback2);

			var rex = new Dog();
			
			var callback3 = function() { counter = counter + 5 };
			var callback4 = function() { counter = counter + 5 };
			
			rex.Bark(callback3);
			rex.Bark(callback4);
			
			fido.Bark();
			assertEquals(2, counter);
			
			rex.Bark();
			assertEquals(12, counter);

		}

    </script>
</head>
<body>
</body>
</html>